import sympy as sp
import numpy as np
import matplotlib.pyplot as plt

#支持中文
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
# 支持负数
plt.rcParams['axes.unicode_minus'] = False

# 定义函数
def f(x):
    return x**3 - 3*x**2 + 2

# 符号计算
x = sp.symbols('x')
f_sym = x**3 - 3*x**2 + 2
f_prime = sp.diff(f_sym, x)
f_double_prime = sp.diff(f_prime, x)

print("函数f(x)的导数是:", f_prime)
print("函数f(x)的二阶导数是:", f_double_prime)

# 求临界点
critical_points = sp.solve(f_prime, x)
print("临界点是:", critical_points)

# 判断极值类型并计算极值
for point in critical_points:
    second_deriv_value = f_double_prime.subs(x, point)
    func_value = f_sym.subs(x, point)
    
    if second_deriv_value > 0:
        print(f"x={point}是极小值点，极小值为f({point})={func_value}")
    elif second_deriv_value < 0:
        print(f"x={point}是极大值点，极大值为f({point})={func_value}")
    else:
        print(f"x={point}可能是拐点")

# 可视化
x_vals = np.linspace(-1, 3, 400)
y_vals = [f(val) for val in x_vals]

plt.figure(figsize=(10, 6))
plt.plot(x_vals, y_vals, 'b-', linewidth=2, label=r'$f(x) = x^3 - 3x^2 + 2$')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.grid(True, alpha=0.3)

# 标记极值点
for point in critical_points:
    y_val = float(f_sym.subs(x, point))
    plt.scatter(point, y_val, color='red', s=100, zorder=5)
    plt.annotate(f'极值点({point}, {y_val})', 
                xy=(point, y_val), xytext=(10, 20),
                textcoords='offset points', arrowprops=dict(arrowstyle='->'))

plt.legend()
plt.show()